/**
 * 
 */
package cc.creativecomputing.demo.timeline;

import static org.junit.Assert.*;

import java.util.ArrayList;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import cc.creativecomputing.timeline.model.TrackData;
import cc.creativecomputing.timeline.model.points.ControlPoint;
import cc.creativecomputing.timeline.model.points.ControlPoint.ControlPointType;


/**
 * @author robert
 *
 */
public class TestTrackData {
	
	private TrackData _myTestSet;
	private ControlPoint _myP0;
	private ControlPoint _myP1;
	private ControlPoint _myP2_1;
	private ControlPoint _myP2_2;
	private ControlPoint _myP2_3;
	private ControlPoint _myP3;
	private ControlPoint _myP4;

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		_myTestSet = new TrackData(null);
		_myP0 = new ControlPoint(0, 0.0, ControlPointType.LINEAR);
		_myP1 = new ControlPoint(1, 1.0, ControlPointType.LINEAR);
		_myP2_1 = new ControlPoint(2, 0.0, ControlPointType.LINEAR);
		_myP2_2 = new ControlPoint(2, 0.5, ControlPointType.LINEAR);
		_myP2_3 = new ControlPoint(2, 1.0, ControlPointType.LINEAR);
		_myP3 = new ControlPoint(3, 0.0, ControlPointType.LINEAR);
		_myP4 = new ControlPoint(4, 0.5, ControlPointType.LINEAR);
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#ControlPointSet()}.
	 */
	@Test
	public void testControlPointSet() {
		assertTrue(_myTestSet.size() == 0);
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#add(cc.creativecomputing.timeline.model.points.ControlPoint)}.
	 */
	@Test
	public void testAdd() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		ControlPoint myP1Clone = _myP1.clone();
		myP1Clone.cutLoose();
		_myTestSet.add(myP1Clone);

		assertFalse(_myP0.hasPrevious());
		assertTrue(_myP0.getNext().equals(_myP1));
		assertTrue(_myTestSet.size() == 2);
			
		_myTestSet.add(_myP3);
		
		assertTrue(_myP3.getPrevious().equals(_myP1));
		
		_myTestSet.add(_myP2_1);
		
		assertTrue(_myP3.getPrevious().equals(_myP2_1));
		assertTrue(_myP2_1.getNext().equals(_myP3));
		assertTrue(_myP2_1.getPrevious().equals(_myP1));
		
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		
		assertFalse(_myP3.hasNext());
		assertTrue(_myP2_3.getNext().equals(_myP3));
		assertTrue(_myP3.getPrevious().equals(_myP2_3));
		assertTrue(_myP2_1.hasNext());
		assertTrue(_myP2_1.getNext().equals(_myP2_2));
		assertTrue(_myP2_3.getPrevious().equals(_myP2_2));
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#getFirstPointAt(double)}.
	 */
	@Test
	public void testGetFirstPointAt() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		assertTrue(_myTestSet.getFirstPointAt(0).equals(_myP0));
		assertTrue(_myTestSet.getFirstPointAt(1).equals(_myP1));
		assertTrue(_myTestSet.getFirstPointAt(2).equals(_myP2_1));
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#getLastPointAt(double)}.
	 */
	@Test
	public void testGetLastPointAt() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		assertTrue(_myTestSet.getLastPointAt(0).equals(_myP0));
		assertTrue(_myTestSet.getLastPointAt(1).equals(_myP1));
		assertTrue(_myTestSet.getLastPointAt(2).equals(_myP2_2));
	}
	
	/**
	 * Test method for {@link de.artcom.timeline.ControlPointSet#move(de.artcom.timeline.CurvePoint, java.awt.geom.Point2D){
	 */
	@Test
	public void testMove() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP3);
		_myTestSet.add(_myP4);
		
		// when moving from the left side to a occupied position
		// insert the point before the existing point
		ControlPoint myTargetPosition = new ControlPoint(2, 0.8);
		_myTestSet.move(_myP1, myTargetPosition);
		assertTrue(_myP1.getPrevious().equals(_myP0));
		assertTrue(_myP1.getNext().equals(_myP2_1));
		assertTrue(_myP2_1.getPrevious().equals(_myP1));
		
		// when moving from the right side to an occupied position
		// insert the point after the existing point
		myTargetPosition.value(0.9);
		_myTestSet.move(_myP3, myTargetPosition);
		assertTrue(_myP2_1.getNext().equals(_myP3));
		assertTrue(_myP3.getPrevious().equals(_myP2_1));
		assertTrue(_myP3.getNext().equals(_myP4));
		
		// also keep connectivity when moving on the same x position
		myTargetPosition.value(0.0);
		_myTestSet.move(_myP3, myTargetPosition);
		assertTrue(_myP2_1.getNext().equals(_myP3));
		assertTrue(_myP3.getPrevious().equals(_myP2_1));
		assertTrue(_myP3.getNext().equals(_myP4));
	}
	
	/**
	 * Test method for {@link de.artcom.timeline.ControlPointSet#insertAll(java.util.ArrayList<CurvePoint>)}.
	 */
	@Test
	public void testInsertAll() {
		
		System.out.println("INSERT ALL");
		// basic set	
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP2_1);
		
		// range to be inserted (p1 to p4) 
		ArrayList<ControlPoint> myRange = new ArrayList<ControlPoint>();
		myRange.add(_myP1);
		myRange.add(_myP2_2);
		myRange.add(_myP2_3);
		myRange.add(_myP3);
		myRange.add(_myP4);
		
		_myTestSet.insertAll(1, 4,myRange);
		myRange = _myTestSet.rangeList(_myP0.time(), _myP2_1.time());
		assertTrue(myRange.size() == 7);
		assertTrue(myRange.get(0).equals(_myP0));
		assertTrue(myRange.get(1).time() == 2); // p1
		assertTrue(myRange.get(2).time() == 3); // p2_2
		assertTrue(myRange.get(3).time() == 3); // p2_3
		assertTrue(myRange.get(4).time() == 4); // p3 
		assertTrue(myRange.get(5).time() == 5); // p4
		assertTrue(myRange.get(6).time() == 6); // p5
	}
	
	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#cutRange(double,double)}.
	 */
	@Test
	public void testCutRange() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		_myTestSet.add(_myP3);
		_myTestSet.add(_myP4);
		
		_myTestSet.cutRange(1, 2.5);
		ArrayList<ControlPoint> myRange = _myTestSet.rangeList(0, 4);
		assertTrue(myRange.size() == 3);
		assertTrue(myRange.get(0).time() == 0);
		assertTrue(myRange.get(1).time() == 1.5);
		assertTrue(myRange.get(2).time() == 2.5);
	}
	
	/**
	 * Test method for {@link de.artcom.timeline.ControlPointSet#replaceAll(java.util.ArrayList<CurvePoint>)}.
	 */
	@Test
	public void testReplaceAll() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		_myTestSet.add(_myP3);
		_myTestSet.add(_myP4);
		
		ArrayList<ControlPoint> myRange = new ArrayList<ControlPoint>();
		ControlPoint myA1 = new ControlPoint(1,1);
		myRange.add(myA1);
		ControlPoint myA2 = new ControlPoint(2,1);
		myRange.add(myA2);
		ControlPoint myA3_1 = new ControlPoint(2.5, 0);
		myRange.add(myA3_1);
		ControlPoint myA3_2 = new ControlPoint(2.5, 0.5);
		myRange.add(myA3_2);
		ControlPoint myA4 = new ControlPoint(2.7, 1);
		myRange.add(myA4);
		
		_myTestSet.replaceAll(1,3, myRange);
		
		myRange = _myTestSet.rangeList(0, 4);
		
		assertTrue(myRange.size() == 7);
		assertTrue(myRange.get(0).equals(_myP0));
		assertTrue(myRange.get(1).equals(new ControlPoint(2.0,1.0)));
		assertTrue(myRange.get(2).equals(new ControlPoint(3.0,1.0)));
		assertTrue(myRange.get(3).equals(new ControlPoint(3.5,0)));
		assertTrue(myRange.get(4).equals(new ControlPoint(3.5,0.5)));
		assertTrue(myRange.get(5).equals(new ControlPoint(3.7,1)));
		assertTrue(myRange.get(6).equals(_myP4));
		
		
	}
	
	@Test
	public void testCopyPaste() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		_myTestSet.add(_myP3);
		_myTestSet.add(_myP4);
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#isEmpty()}.
	 */
	@Test
	public void testIsEmpty() {
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		assertTrue(!_myTestSet.isEmpty());
		_myTestSet.remove(_myP2_1);
		assertTrue(!_myTestSet.isEmpty());
		_myTestSet.remove(_myP2_2);
		assertTrue(_myTestSet.isEmpty());
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#rangeList(double, double)}.
	 */
	@Test
	public void testRangeList() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		_myTestSet.add(_myP3);
		ArrayList<ControlPoint> myRange = _myTestSet.rangeList(1, 2);
		assertTrue(myRange.get(0).equals(_myP1));
		assertTrue(myRange.get(1).equals(_myP2_1));
		assertTrue(myRange.get(2).equals(_myP2_2));
		assertTrue(myRange.get(3).equals(_myP2_3));
		assertTrue(myRange.size() == 4);
		
		myRange = _myTestSet.rangeList(1.1, 1.9);
		assertTrue(myRange.size() == 0);
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#remove(cc.creativecomputing.timeline.model.points.ControlPoint)}.
	 */
	@Test
	public void testRemove() {
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		_myTestSet.add(_myP3);	
		_myTestSet.remove(_myP2_2);
		assertTrue(_myP2_1.getNext().equals(_myP2_3));
		assertTrue(_myP2_3.getPrevious().equals(_myP2_1));
		_myTestSet.remove(_myP2_1);
		assertTrue(_myP1.getNext().equals(_myP2_3));
		_myTestSet.remove(_myP2_3);
		assertTrue(_myP1.getNext().equals(_myP3));
	}

	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#removeAll(double, double)}.
	 */
	@Test
	public void testRemoveAll() {
		System.out.println("REMOVE ALL");
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		_myTestSet.add(_myP3);
		_myTestSet.removeAll(0,3); 
		assertTrue(_myTestSet.isEmpty());
		assertTrue(_myTestSet.size() == 0);
		
		_myTestSet.add(_myP0);
		_myTestSet.add(_myP1);
		_myTestSet.add(_myP2_1);
		_myTestSet.add(_myP2_2);
		_myTestSet.add(_myP2_3);
		_myTestSet.add(_myP3);
		_myTestSet.removeAll(1.5, 1.8);
		assertTrue(_myTestSet.size() == 6);
	}
	
	
	
	/**
	 * Test method for {@link cc.creativecomputing.timeline.model.TrackData#size()}.
	 */
	@Test
	public void testSize() {
		assertTrue(_myTestSet.size() == 0);
		_myTestSet.add(_myP0);
		assertTrue(_myTestSet.size() == 1);
		_myTestSet.add(_myP1);
		assertTrue(_myTestSet.size() == 2);
		_myTestSet.add(_myP2_1);
		assertTrue(_myTestSet.size() == 3);
		_myTestSet.add(_myP2_2);
		assertTrue(_myTestSet.size() == 4);
		_myTestSet.add(_myP2_3);
		assertTrue(_myTestSet.size() == 5);
		_myTestSet.add(_myP3);
		assertTrue(_myTestSet.size() == 6);
	}

}
